#include <iostream>
using namespace std;
template<typename T>
class Ptr_to_T
{
public:
    class Range{};
    
    Ptr_to_T(T* p, T* array, int size):_p(p),_array(array),_size(size){
    }
    Ptr_to_T(T* p):_p(p){}
    Ptr_to_T& operator++(){//prefix
        _p += 1;
        return *this;
    }
    const Ptr_to_T operator++(int){//postfix
        T* temp = _p;
        _p += 1;
        return Ptr_to_T(temp, temp, _array + _size - temp);
    }
    Ptr_to_T& operator--(){//prefix
        _p--;
        return *this;
    }
    const Ptr_to_T operator--(int){//postfix
        T* temp = _p;
        _p -= 1;
        return Ptr_to_T(temp, temp, _array + _size -temp);
    }
    T& operator*(){
        check();
        return *_p;
    }
private:
    void check(){
        if( _p - _array >= _size || _p < _array){
            cout <<  _p - _array << endl;
            throw Range();
        }
    }
            
    T* _p;
    T* _array;
    int _size;
};
int main()
{
    int array[10];
    Ptr_to_T<int> smart_ptr(&array[0], array, 10);
/*    *smart_ptr++ = 10;
    *smart_ptr = 100;
    cout << array[0] << endl;
    cout << array[1] << endl;*/

    int array2[10];
    Ptr_to_T<int> sp(&array2[0], array2, 10);
/*    *++sp = 10;
    *sp = 20;
    cout << array2[0] << endl;
    cout << array2[1] << endl;*/

    try{
        //sp++++;
        sp--;
        sp--;
        sp--;
        sp--;
        sp--;
        sp--;
        sp--;
        sp--;
        sp--;
        sp--;
        sp--;
        sp--;
        sp--;
        sp--;
        *sp;
        
        sp++;
        sp++;
        sp++;
        sp++;
        sp++;
        sp++;
        sp++;
        sp++;
        sp++;
        sp++;
        sp++;
        sp++;
        sp++;
        sp++;
        sp++;
        sp++;
        sp++;
        sp++;
        
        int i = 10;
        cout << i << endl;
        
        *smart_ptr = 200;
        *sp = 20;
    }
    catch(Ptr_to_T<int>::Range& r)
    {
        cout << "Out of range!" << endl;
    }
    
    
}
